#pragma once

#include <cstdint>

/*
拆分目标：
1. 编写一个单例类的Application
2. 成员变量 + 成员函数
    2.1 init
    2.2 update
    2.3 destroy
3. 编写一个OnResize函数，响应窗体大小变化
    3.1 声明一个函数指针resizeCallback
    3.2 声明一个resizeCallback类型的成员变量
    3.3 声明一个setResizeCallback的函数，设置窗体变化响应回调函数
    3.4 声明一个static的静态函数，相应glfw窗体变化
    3.5 将静态函数设置到glfw的监听当中
    3.6 * 学会使用glfw的UserPointer
4. 响应键盘消息函数——OnKeyboard
    4.1 声明静态函数，用于响应glfw的键盘事件
    4.2 将静态函数设置到glfw的监听KeyCallback当中
    4.3 声明一个函数指针KeyOperationCallback
    4.4 声明一个KeyOperationCallback类型的的成员变量
    4.5 声明一个SetKeyOperationCallback的函数，用来设置键盘响应回调函数
*/

// #define app Application::getInstance()

using ResizeCallback = void (*)(int, int);
using KeyOperationCallback = void (*)(int key, int action, int mods);

class GLFWwindow;
class Application {
public:
  ~Application();

  // 用于访问实例的静态函数
  static Application *getInstance();

  bool init(const int &width, const int &height);
  bool update();
  void destroy();

  uint32_t getWidth() const { return mWidth; }
  uint32_t getHeight() const { return mHeight; }

  void setResizeCallback(ResizeCallback callback) {
    mResizeCallback = callback;
  }

  void setKeyOperationCallback(KeyOperationCallback callback) {
    mKeyOperationCallback = callback;
  }

private:
  Application();
  // 全局唯一的静态变量实例
  static Application *mInstance;
  uint32_t mWidth{0};
  uint32_t mHeight{0};
  GLFWwindow *mWindow{nullptr};

  ResizeCallback mResizeCallback{nullptr};
  KeyOperationCallback mKeyOperationCallback{nullptr};

  static void frameBufferSizeCallback(GLFWwindow *window, int width,
                                      int height);
  static void keyCallback(GLFWwindow *window, int key, int scancode, int action,
                          int mods);
};
